//
//  MTHttpTool.m
//  MeToo
//
//  Created by 俊松何 on 2018/7/3.
//  Copyright © 2018年 tianxie. All rights reserved.
//

#import "MTHttpTool.h"
#import <AliyunOSSiOS/OSSService.h>
#import "CommonCrypto/CommonDigest.h"

@implementation MTBaseData
@end

@implementation MTError
+ (instancetype)errorWithDescription:(NSString *)Description
                                code:(NSInteger)Code
{
    MTError *error = [[MTError alloc] init];
    error.errorDescription = Description;
    error.code = Code;
    return error;
}
+ (instancetype) netWorkError
{
    return [self errorWithDescription:@"网络错误" code:-1];
}
@end


@interface MTHttpTool()
@property(nonatomic,strong) AFHTTPSessionManager *manager;
@end

static MTHttpTool *tool=nil; //放入外部

@implementation MTHttpTool

+(instancetype)shareTool
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        tool  = [[MTHttpTool alloc] init];
        tool.manager = [AFHTTPSessionManager manager];
        tool.manager.operationQueue.maxConcurrentOperationCount = 5;
        tool.manager.requestSerializer.timeoutInterval = 20;
        tool.manager.requestSerializer = [AFHTTPRequestSerializer serializer];
        tool.manager.responseSerializer = [AFJSONResponseSerializer serializer];
        tool.manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/plain",@"text/html",@"text/javascript", nil];
        [tool.manager.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [tool.manager.requestSerializer setValue:@"1" forHTTPHeaderField:@"platform"];
        
        NSString *language =   [InternationalControl currentLanguage];
        [tool.manager.requestSerializer setValue:language forHTTPHeaderField:@"language"];
        
        NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
        // app版本
        NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
        [tool.manager.requestSerializer setValue:app_Version forHTTPHeaderField:@"versionName"];
    });
    return tool;
}

-(void)postPath:(NSString *)path
     parameters:(NSDictionary *)parameters
        success:(MTSuccess)success
         failer:(MTFailer)failer
{
    
    NSString *fullpath = [NSString stringWithFormat:@"%@%@",mtbasePath,path];
    if([MTUserDataManager manager].cutrrentUser)
    {
        NSDictionary *dict = @{
                               @"userId":[MTUserDataManager manager].cutrrentUser.userId,
                               @"token":[MTUserDataManager manager].cutrrentUser.token
                               };
        NSString *jsonstr = [dict mj_JSONString];
        NSString *cryptoken =    [LTAESTool decryptAES:jsonstr key:passwordCrypkey kVector:passwordCrypInvterKey];
        [tool.manager.requestSerializer setValue:cryptoken forHTTPHeaderField:@"xtoken"];
    }
    
    DLog(@"%@\n%@",fullpath,parameters);
    [_manager POST:fullpath parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        MTBaseData *model = [MTBaseData mj_objectWithKeyValues:responseObject];
        NSString* jsonStr = [responseObject mj_JSONString];
        //解析结果
        DLog(@"Response  -->\n response object:\n%@\n, json data:\n%@\n",
             responseObject, jsonStr);
        
        if(model.code == 1)
        {
            success(model);
        }else if(model.code == 400 || model.code == 401)
        {
//            [[NSNotificationCenter defaultCenter] postNotificationName:LoginTokenError object:model.message];
            MTError *mterror = [MTError errorWithDescription:model.message code:model.code];
             failer(mterror);
        }
        else
        {
            MTError *mterror = [MTError errorWithDescription:model.message code:model.code];
            failer(mterror);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        NSString* errorStr = [NSErrorHelper handleErrorMessage:error];
        MTError *mterror = [MTError errorWithDescription:errorStr code:error.code];
        
        failer(mterror);
        DLog(@"Response  -->\n"
             "URL:  %@\n"
             "error:\n%@\n",
             task.currentRequest.URL, error);
    }];
}


-(void)getPath:(NSString *)path
    parameters:(NSDictionary *)parameters
       success:(MTSuccess)success
        failer:(MTFailer)failer
{
    NSString *fullpath = [NSString stringWithFormat:@"%@%@",mtbasePath,path];
    if([MTUserDataManager manager].cutrrentUser)
    {
        NSDictionary *dict = @{
                               @"userId":[MTUserDataManager manager].cutrrentUser.userId,
                               @"token":[MTUserDataManager manager].cutrrentUser.token
                               };
        NSString *jsonstr = [dict mj_JSONString];
        NSString *cryptoken =    [LTAESTool decryptAES:jsonstr key:passwordCrypkey kVector:passwordCrypInvterKey];
        [tool.manager.requestSerializer setValue:cryptoken forHTTPHeaderField:@"xtoken"];
    }
    DLog(@"%@\n%@",fullpath,parameters);
    [_manager GET:fullpath parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        MTBaseData *model = [MTBaseData mj_objectWithKeyValues:responseObject];
        //解析结果
        NSLog(@"Response  -->\n response object:\n%@\n",
              responseObject);
        if(model.code == 1)
        {
            success(model);
        }else if(model.code == 400 || model.code == 401)
        {
//             [[NSNotificationCenter defaultCenter] postNotificationName:LoginTokenError object:model.message];
            MTError *mterror = [MTError errorWithDescription:model.message code:model.code];
            failer(mterror);
        }
        else
        {
            MTError *mterror = [MTError errorWithDescription:model.message code:model.code];
            failer(mterror);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSString* errorStr = [NSErrorHelper handleErrorMessage:error];
        MTError *mterror = [MTError errorWithDescription:errorStr code:error.code];
        failer(mterror);
        DLog(@"Response  -->\n"
             "URL:  %@\n"
             "error:\n%@\n",
             task.currentRequest.URL, error);
    }];
}

#pragma mark - 上传多张图片方法
-(void)uploadImages:(NSArray *)images
           complete:(void(^)(NSArray<NSDictionary *> *names, MTError *mterror))complete {
    
    
    NSInteger count = images.count;
    NSMutableArray *urls = [NSMutableArray arrayWithCapacity:4];
    __block int successCount = 0;
    
    for (int i = 0; i < count; i++) {
        
        NSData *data = UIImageJPEGRepresentation(images[i], 0.3);
        [self uploadImageData:data progress:^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
            
        } success:^(NSString *fileUrl, LTFileTokenModel *model) {
            successCount = successCount + 1;
            
            NSDictionary *indexModel = @{@"url":fileUrl,@"index":@(successCount)};
            [urls addObject:indexModel];
            if(successCount == count)
            {
                complete(urls,nil);
            }
        } failer:^(MTError *lterror) {
            
            complete(nil,lterror);
            
        }];
        
    }
    
}




-(void)uploadImageData:(NSData *)data
              progress:(void(^)(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend))uploadProgress
               success:(void(^)(NSString *remotePath,LTFileTokenModel *model))success
                failer:(void(^)(MTError *lterror))failer
{
    
    NSString *objectName = [self fileNameWithSuffix:@"jpg"];
    
    [self getUploadTokenWithType:FileTypeNormal  success:^(LTFileTokenModel *model) {
        
        NSString *failePath =  [NSTemporaryDirectory() stringByAppendingString:objectName];
        [[NSFileManager defaultManager] createFileAtPath:failePath contents:data attributes:nil];
        model.objectKey = objectName;
        
        id<OSSCredentialProvider> credential = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:model.access_key_id secretKeyId:model.access_key_secret securityToken:model.token];
        
        OSSClient *client = [[OSSClient alloc] initWithEndpoint:model.oss_end_point credentialProvider:credential];
        
        
        OSSPutObjectRequest * put = [OSSPutObjectRequest new];
        
        put.bucketName = model.bucket_name;
        put.objectKey = objectName;
        
        put.uploadingData = data;
        
        put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
            NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
            //            int currentPercent = percent * 100;
//            uploadProgress(bytesSent,totalByteSent,totalBytesExpectedToSend);
        };
        
        OSSTask * putTask = [client putObject:put];
        
        [putTask continueWithBlock:^id(OSSTask *task) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (!task.error) {
                    NSLog(@"upload object success!");
                    success([NSString stringWithFormat:@"%@%@",model.oss_url,objectName],model);
                } else {
                    NSLog(@"upload object failed, error: %@" , task.error);
                    MTError *lterror = [MTError errorWithDescription:@"upload object failed" code:-1];
                    failer(lterror);
                }
            });
            return nil;
        }];
    } failer:^(MTError *lterror) {
        failer(lterror);
    }];
}


-(void)getUploadTokenWithType:(FileType)type success:(void(^)(LTFileTokenModel *model))success failer:(void(^)(MTError *lterror))failer
{
    
    NSTimeInterval time_stamp = [[NSDate date] timeIntervalSince1970];
    NSInteger time_senonds = time_stamp;
    NSString *md5str = [self MD5StringForString:[NSString stringWithFormat:@"%@%d%ld",md5key,type,time_senonds]];
    
    NSDictionary *param = @{@"type":@(type),
                            @"time_stamp":@(time_senonds),
                            @"fileName":md5str,
                            };
    [self getPath:@"/commons/upload/get_info" parameters:param success:^(MTBaseData *datamodel) {
        
        LTFileTokenModel *tokenModel = [LTFileTokenModel mj_objectWithKeyValues:datamodel.data];
        success(tokenModel);
    } failer:^(MTError *error) {
        failer(error);
    }];
}


-(void)uploadFileData:(NSData *)data
             FileType:(FileType)type
             progress:(void(^)(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend))uploadProgress
              success:(void(^)(NSString *fileUrl,LTFileTokenModel *model))success
               failer:(void(^)(MTError *lterror))failer
{
    
    NSString *suffix = nil;
    switch (type) {
        case FileTypeNormal: suffix = @"jpg";break;
        case FileTypeVoice:  suffix = @"amr";break;
        case FileTypeVideo:  suffix = @"mp4";break;
        default:  break;
    }
    
    NSString *objectName = [self fileNameWithSuffix:suffix];
    [self getUploadTokenWithType:type  success:^(LTFileTokenModel *model) {
        
        NSString *failePath =  [NSTemporaryDirectory() stringByAppendingString:objectName];
        [[NSFileManager defaultManager] createFileAtPath:failePath contents:data attributes:nil];
        model.objectKey = objectName;
        
        id<OSSCredentialProvider> credential = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:model.access_key_id secretKeyId:model.access_key_secret securityToken:model.token];
        
        OSSClient *client = [[OSSClient alloc] initWithEndpoint:model.oss_end_point credentialProvider:credential];
        
        
        OSSPutObjectRequest * put = [OSSPutObjectRequest new];
        
        put.bucketName = model.bucket_name;
        put.objectKey = model.objectKey;
        
        put.uploadingData = data;
        
        put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
            NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
            if(uploadProgress)
            {
                uploadProgress(bytesSent,totalByteSent,totalBytesExpectedToSend);
            }
        };
        
        OSSTask * putTask = [client putObject:put];
        
        [putTask continueWithBlock:^id(OSSTask *task) {
            if (!task.error) {
                NSLog(@"upload object success!");
                success([NSString stringWithFormat:@"%@%@",model.oss_url,objectName],model);
            } else {
                NSLog(@"upload object failed, error: %@" , task.error);
                MTError *lterror = [MTError errorWithDescription:@"upload object failed" code:-1];
                failer(lterror);
            }
            return nil;
        }];
    } failer:^(MTError *lterror) {
        failer(lterror);
    }];
    
}




-(NSString *)MD5StringForString:(NSString *)str{
    
    const char *cStr = [str UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (unsigned int)strlen(cStr), result);
    
    return [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
             result[0], result[1], result[2], result[3],
             result[4], result[5], result[6], result[7],
             result[8], result[9], result[10], result[11],
             result[12], result[13], result[14], result[15]
             ] lowercaseString];
    
}

//文件命名
-(NSString *)fileNameWithSuffix:(NSString *)suffix
{
    //随机数
    int rand = arc4random() % 1000;
    long filename = [[NSDate date] timeIntervalSince1970] * 1000;
    NSString *objectName = [NSString stringWithFormat:@"%d%ld.%@",rand,filename,suffix];
    return objectName;
}

//下载文件临时存放路径
-(NSString *)fileTempPathWithSuffix:(NSString *)suffix
{
    NSString *filename = [self fileNameWithSuffix:suffix];
    NSString *filePath =  [NSTemporaryDirectory() stringByAppendingString:filename];
    return filePath;
}



@end
